package com.ruoyi.system.api.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.config.Global;
import com.ruoyi.common.utils.AMapUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.LngLat;
import com.ruoyi.common.utils.OkHttpUtils;
import com.ruoyi.system.api.ResponseWithData;
import com.ruoyi.system.api.domain.Configuration;
import com.ruoyi.system.api.domain.FseLocation;
import com.ruoyi.system.api.domain.FseLocationLog;
import com.ruoyi.system.api.domain.InstrumentInfo;
import com.ruoyi.system.api.domain.User;
import com.ruoyi.system.api.domain.dto.FseLocationDto;
import com.ruoyi.system.api.mapper.ConfigurationMapper;
import com.ruoyi.system.api.mapper.FseLocationLogMapper;
import com.ruoyi.system.api.mapper.FseLocationMapper;
import com.ruoyi.system.api.mapper.InstrumentInfoMapper;
import com.ruoyi.system.api.mapper.UserMapper;
import com.ruoyi.system.api.service.CcService;
import com.ruoyi.system.api.service.IConfigurationService;
import com.ruoyi.system.api.service.IInterfaceOperationLogService;
import com.ruoyi.system.api.service.LocationService;
import com.sun.org.apache.xerces.internal.impl.xpath.regex.ParseException;

import okhttp3.Response;
import org.springframework.util.ObjectUtils;


/**
 * @ClassName LoginServiceImpl
 * @Description: TODO
 * @Author shihx
 * @Date 2020/2/24
 * @Version V1.0
 **/
@Service
public class LocationServiceImpl implements LocationService {

    private static final Logger log = LoggerFactory.getLogger(LocationServiceImpl.class);

    /**
     * 配置文件
     */
    @Autowired
    private Global global;

    /**
     * 用户表
     */
    @Autowired
    private UserMapper userMapper;

    /**
     * 接口调用日志
     */
    @Autowired
    private IInterfaceOperationLogService iInterfaceOperationLogService;

    /**
     * 用户实时位置表
     */
    @Autowired
    private FseLocationMapper fseLocationMapper;

    /**
     * 用户历史位置表
     */
    @Autowired
    private FseLocationLogMapper fseLocationLogMapper;

    /**
     * 仪器 历史数据初始化到此，CC有新仪器同步到此Mapper
     */
    @Autowired
    private InstrumentInfoMapper instrumentInfoMapper;

    /**
     * 调用CC接口service
     */
    @Autowired
    private CcService ccService;

    /* 参数配置mapper */
    @Autowired
    private ConfigurationMapper configurationMapper;

    @Autowired
    private IConfigurationService configurationService;


    @Override
    public ResponseWithData<?> getFseLocation(String teamleaderId, String name, String enginnerId) throws Exception {

        if (!DateUtils.isWorkTime() || !DateUtils.isDatePeriod()) {
            log.info("不在工作时间");
            return new ResponseWithData<>().success(new ArrayList<>()).msg("查询成功").code(200);
        }

        Configuration configuration = new Configuration();
        configuration.setName("network_state");
        List<Configuration> configurations = configurationMapper.selectConfigurationList(configuration);
        Long network_stateConf = new Long(configurations.get(0).getValue());
        long resiveTime = new Date().getTime() - network_stateConf * 60 * 1000;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置格式
        String receiveDate = format.format(resiveTime);
        List<User> list = userMapper.getFseLocationAndAddressSY(teamleaderId, name, enginnerId, receiveDate);
        for (User user : list) {
            Date receiveTime = user.getReceiveDate();
            if (receiveTime != null) {
                long diff = new Date().getTime() - receiveTime.getTime();
                long nd = 1000 * 24 * 60 * 60;
                long nh = 1000 * 60 * 60;
                long nm = 1000 * 60;
                long min = diff % nd % nh / nm;
                if (min < network_stateConf) {
                    //在线
                    user.setOnline("1");
                } else {
                    // 离线
                    user.setOnline("0");
                }
            } else {
                user.setOnline("1");
            }
        }
        return new ResponseWithData<>().success(list).msg("查询成功").code(200);
    }

    @Override
    public ResponseWithData<?> reportLocation(FseLocationDto data) throws Exception {
        List<FseLocation> fseLocationList = data.getFseLocationList();
        if (fseLocationList != null && fseLocationList.size() > 0) {

            User user = new User();
            user.setEnginnerId(Long.parseLong(fseLocationList.get(0).getFseId()));
            List<User> users = userMapper.selectUserList(user);
            if (users != null && users.size() > 0) {
                if (StringUtils.isNotEmpty(users.get(0).getWorkday())) {
                    if ("3".equals(users.get(0).getWorkday())) {
                        return new ResponseWithData<>().error().msg("当前处于休假状态").code(200);
                    }
                }
            }

            for (FseLocation fseLocation : fseLocationList) {
                /** 调用高德api 根据经纬线逆解析用户所在地址 */
                String address = "";
                String url = global.getGaodeApi().replaceAll("KEY", global.getGaodeKey())
                        .replaceAll("LOCATION", fseLocation.getPostx() + "," + fseLocation.getPosty());
                Response res = OkHttpUtils.getInstance().getRequest(url.toString(), null);
                if (res.code() == 200) {
                    String reponseBody = res.body().string();
                    log.info("高德地址逆解析返回结果：" + reponseBody);
                    JSONObject obj = JSON.parseObject(reponseBody);
                    if ("1".equals(obj.getString("status"))) {
                        address = obj.getJSONObject("regeocode").getString("formatted_address");
                        fseLocation.setAddress(address);
                        log.info("高德逆解析地址：" + address);
                    }
                }

                /** 验证经纬度实时库中是否存在此工程师的位置信息 */
                FseLocation fl = new FseLocation();
                fl.setFseId(fseLocation.getFseId());
                List<FseLocation> flList = fseLocationMapper.selectFseLocationList(fl);
                if (flList != null && flList.size() > 0) {
                    fseLocation.setId(flList.get(0).getId());
                    fseLocation.setUpdateTime(new Date());
                    fseLocation.setStateDescribe("");
                    fseLocationMapper.updateFseLocation(fseLocation);
                } else {
                    fseLocation.setCreateTime(new Date());
                    fseLocationMapper.insertFseLocation(fseLocation);
                }

                /** 所有位置信息存入log表中，用于轨迹查询 */
                FseLocationLog fseLocationLog = new FseLocationLog();
                fseLocationLog.setAddress(address);
                fseLocationLog.setFseId(fseLocation.getFseId());
                fseLocationLog.setFseName(fseLocation.getFseName());
                fseLocationLog.setPostx(fseLocation.getPostx());
                fseLocationLog.setPosty(fseLocation.getPosty());
                fseLocationLog.setNetworkState(fseLocation.getNetworkState());
                fseLocationLog.setReceiveDate(fseLocation.getReceiveDate());
                fseLocationLog.setState(fseLocation.getState());
                fseLocationLog.setStateDescribe(fseLocation.getStateDescribe());
                fseLocationLog.setCreateTime(new Date());
                fseLocationLog.setAltitude(fseLocation.getAltitude());
                fseLocationLog.setSpeed(fseLocation.getSpeed());
                fseLocationLog.setCourse(fseLocation.getCourse());
                fseLocationLog.setType("1");
                fseLocationLogMapper.insertFseLocationLog(fseLocationLog);
            }
        }

        return new ResponseWithData<>().success().msg("位置信息上传成功").code(200);
    }

    @Override
    public ResponseWithData<?> getSentFseList(String ServiceNoticeId) throws Exception {
        List<FseLocation> list = fseLocationMapper.getSentFseList(ServiceNoticeId);
        return new ResponseWithData<>().success(list).msg("查询成功").code(200);
    }

    @Override
    public ResponseWithData<?> getToBeAppointedFse(String ServiceNoticeId, String TeamleaderId, String name) throws Exception {

        if (StringUtils.isNotEmpty(name)) {
            /** 调用CC端接口2.50获取其他工程师接口 */
            ccService.getEngineerByName(name, ServiceNoticeId, TeamleaderId);
            TeamleaderId = "";
        } else {
            /** 调用CC端接口同步更新TL名下FSE信息 */
            ccService.getEngineerByTL(ServiceNoticeId, TeamleaderId, "getToBeAppointedFse");
        }
        /** 通过本地数据库查询设备信息的经纬度信息 */
        String longitude = "0";
        String latitude = "0";
        List<InstrumentInfo> iiList = instrumentInfoMapper.getInstrumentInfoList(ServiceNoticeId);
        if (iiList != null && iiList.size() > 0) {
            longitude = iiList.get(0).getLongitude() + "";
            latitude = iiList.get(0).getLatitude() + "";
        }
        /** 根据设备的经纬度查询未派工的FSE列表信息 按距离由近到远排序，并统计每个FSE进行中的数量 */
        List<FseLocation> list = fseLocationMapper.getToBeAppointedFse(ServiceNoticeId, TeamleaderId, longitude, latitude, name);
        if (!DateUtils.isWorkTime() || !DateUtils.isDatePeriod()) {
            for (FseLocation fseLocation : list) {
                fseLocation.setAddress("");
                fseLocation.setDistance("-");
            }
        }
        return new ResponseWithData<>().success(list).msg("查询成功").code(200);
    }

    @Override
    public ResponseWithData<?> getLocation(String ServiceNoticeId, String TeamleaderId) throws Exception {
        List<User> list = userMapper.getFseLocation(TeamleaderId);
        /** 通过本地数据库查询设备信息的经纬度信息 */
        List<InstrumentInfo> iiList = instrumentInfoMapper.getInstrumentInfoList(ServiceNoticeId);
        Map map = new HashMap();
        map.put("FseList", list);
        map.put("InstrumentInfoList", iiList);
        return new ResponseWithData<>().success(map).msg("查询成功").code(200);
    }

    @Override
    public Map<String, String> AddressResolution(String address, String city) throws Exception {
        Map<String, String> map = new HashMap<>();
        if (StringUtils.isEmpty(address)) {
            map.put("longitude", "0.00");
            map.put("latitude", "0.00");
            return map;
        }
        String url = global.getGaodeAddress()
                .replaceAll("KEY", global.getGaodeKey())
                .replaceAll("ADDRESS", address)
                .replaceAll("CITY", city);
        Response res = OkHttpUtils.getInstance().getRequest(url.toString(), null);

        boolean state = false;
        if (res.code() == 200) {
            String reponseBody = res.body().string();
            log.info("高德地址解析返回结果：" + reponseBody);
            JSONObject obj = JSON.parseObject(reponseBody);
            if ("1".equals(obj.getString("status"))) {
                try {
                    String location = obj.getJSONArray("geocodes").getJSONObject(0).getString("location");
                    log.info("高德解析地址：" + location);
                    String[] locations = location.split(",");
                    map.put("longitude", locations[0]);
                    map.put("latitude", locations[1]);
                    state = true;
                } catch (Exception e) {
                    log.info("高德地址解析返回结果：" + reponseBody);
                }
            }
        }
        if (!state) {
            map.put("longitude", "0.00");
            map.put("latitude", "0.00");
        }
        return map;
    }

    @Override
    public ResponseWithData<?> getFseLocationLog(String teamleaderId, String fseId, String fseName, String startTime, String endTime) throws Exception {
        List<FseLocationLog> list = fseLocationLogMapper.selectHistoryList(teamleaderId, fseId, fseName, startTime, endTime);
        List<FseLocationLog> fseLocationList = new ArrayList();
        if (!ObjectUtils.isEmpty(list)) {
            fseLocationList = dealWithFseLocationLog(list);
        }
        return new ResponseWithData().success(fseLocationList).msg("查询成功").code(200);
    }

    public List<FseLocationLog> dealWithFseLocationLog(List<FseLocationLog> logList) throws Exception {
        //去掉非工作日，时间数据
        List<FseLocationLog> list = new ArrayList<FseLocationLog>();
        if (null != logList && !logList.isEmpty()) {
            String beginTime = global.getWorkBeginTime();
            String endTimes = global.getWorkEndTime();
            for (FseLocationLog fseLocation : logList) {
                try {
                    Date receiveDate = fseLocation.getReceiveDate();
                    if(ObjectUtils.isEmpty(receiveDate)){
                        continue;
                    }
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String splitData = simpleDateFormat.format(receiveDate);
                    String[] agr = splitData.split(" ");
                    //判断该条数据日期是否是工作日
                    boolean isWeekend = DateUtils.isWeekend(agr[0]);
                    //判断该条数据的时间是否在指定范围内
                    boolean isEffectiveDate = DateUtils.isEffectiveDate(agr[1], beginTime, endTimes);

                    if (isWeekend && isEffectiveDate) {
                        list.add(fseLocation);
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }
        // 配置参数，计算历史点的停留时间
        Double distance = 0D;
        Configuration configuration = new Configuration();
        configuration.setName("geographical_coordinates_distance");
        List<Configuration> configurations = configurationMapper.selectConfigurationList(configuration);
        if (configurations != null && configurations.size() > 0) {
            String val = configurations.get(0).getValue();
            if (com.ruoyi.common.utils.StringUtils.isNotEmpty(val)) {
                distance = Double.parseDouble(val);
            }
        }
        // 定位上报时间间隔
        Long timeLong = 0L;
        configuration.setName("location_reporting_interval");
        configurations = configurationMapper.selectConfigurationList(configuration);
        if (configurations != null && configurations.size() > 0) {
            String val = configurations.get(0).getValue();
            if (com.ruoyi.common.utils.StringUtils.isNotEmpty(val)) {
                timeLong = Long.parseLong(val);
            }
        }
        List<FseLocationLog> result = new ArrayList<>();
        int lastResultIndex = 0; //最新存到result的对象所在list中的下标
        Long waste = 0L;
        for (int i = 0; i < list.size(); i++) {
            if (i > 0) {
                if (!DateUtils.isSameDay(list.get(i-1).getReceiveDate(), list.get(i ).getReceiveDate())) {
                    Date start = list.get(i-1).getReceiveDate();
                    Date end = list.get(i ).getReceiveDate();
                    waste = (end.getTime() - start.getTime()) / (1000 * 60) ;
                }
            }
        }
        for (int i = 0; i < list.size(); i++) {
            FseLocationLog log = list.get(i);
            if (log.getPostx() != null && log.getPosty() != null) {
                if (result.size() == 0) {
                    // 首个标记时 直接存入结果
                    result.add(log);
                    // 更新坐在下标
                    lastResultIndex = i;
                } else if (StringUtils.isNotEmpty(log.getType()) && !log.getType().equals("1")) {
                    // 签到签离时 直接存入结果
                    result.add(log);
                } else {
                    // 距离计算
                    FseLocationLog lastResult = list.get(lastResultIndex);
                    // 人员的实时经纬度
                    LngLat startAdd = new LngLat(log.getPostx(), log.getPosty());
                    // 获取仪器的经纬度
                    LngLat endAdd = new LngLat(lastResult.getPostx(), lastResult.getPosty());
                    // 计算获取两组经纬度的距离 取米
                    double meter1 = AMapUtils.calculateLineDistance(startAdd, endAdd);
                    // 更新上一点的停留时间
                    Date start = lastResult.getReceiveDate();
                    Date end = log.getReceiveDate();
                    long cha = 0; //时间差（分钟）
                    try {
                        cha = DateUtils.timeDiff(start,end);
                        if (!DateUtils.isSameDay(start, end)) {
                            cha -= waste;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if (cha <= timeLong) {//5得是配置的变量
                        cha = 0;
                    } else {
                        cha = cha - timeLong;
                    }
                    lastResult.setLengthOfStay(cha);
                    if (meter1 > distance) { //超出参数设置的距离值
                        // 存入结果
                        result.add(log);
                        // 更新坐在下标（必须放最后）
                        lastResultIndex = i;
                    }
                }
            }
        }
        for (int i = 0; i < result.size(); i++) {
            if(StringUtils.isEmpty(result.get(i).getFseName())){
                if(!StringUtils.isEmpty(result.get(i).getFseId())){
                    List <User>userList =  userMapper.getFseInformation(result.get(i).getFseId());
                    result.get(i).setFseName(userList.get(0).getName());
                }
            }
        }

        return result;
    }


}
